const mongoose = require('mongoose');
const asyncHandler = require('express-async-handler');
const QuestionSource = require('../models/QuestionSource');

/**
 * @swagger
 * /api/question-sources:
 *   post:
 *     summary: 创建题目来源类型和内容
 *     description: 创建新的题目来源类型和内容，sourceType和sourceContent必须同时提供
 *     tags: [QuestionSource]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required: [sourceType, sourceContent]
 *             properties:
 *               sourceType:
 *                 type: string
 *                 description: 题目来源类型
 *               sourceContent:
 *                 type: string
 *                 description: 题目来源内容
 *     responses:
 *       201:
 *         description: 成功创建题目来源
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/QuestionSource'
 *       400:
 *         description: 缺少必要字段或请求格式错误
 *       409:
 *         description: 题目来源类型和内容已存在
 */

// ...其他代码保持不变...

exports.createSource = asyncHandler(async (req, res) => {
  const { sourceType, sourceContent } = req.body;
  if (!sourceType || !sourceContent) {
    res.status(400);
    throw new Error('缺少必要字段');
  }
  
  // 检查是否已存在相同的记录
  const existingSource = await QuestionSource.findOne({ sourceType, sourceContent: sourceContent });
  if (existingSource) {
    res.status(409);
    throw new Error('该题目来源类型和内容已存在');
  }
  
  const newSource = new QuestionSource({ sourceType, sourceContent: sourceContent });
  await newSource.save();
  res.status(201).json({ 
    success: true, 
    data: newSource
  });
});

/**
 * @swagger
 * /api/question-sources/{id}:
 *   get:
 *     summary: 获取单个题目来源文档
 *     description: 根据ID获取特定题目来源文档
 *     tags: [QuestionSource]
 *     parameters:
 *       - in: path
 *         name: id
 *         schema:
 *           type: string
 *         required: true
 *         description: 题目来源文档ID
 *     responses:
 *       200:
 *         description: 成功获取文档
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/QuestionSource'
 *       404:
 *         description: 未找到指定文档
 *       400:
 *         description: ID格式不正确
 */
exports.getSourceById = asyncHandler(async (req, res) => {
  const { id } = req.params;
  
  // 验证文档ID格式
  if (!mongoose.Types.ObjectId.isValid(id)) {
    res.status(400);
    throw new Error('无效的ID格式');
  }
  
  const source = await QuestionSource.findById(id);
  if (!source) {
    res.status(404);
    throw new Error('未找到指定文档');
  }
  
  res.status(200).json({ 
    success: true,
    data: source
  });
});

/**
 * @swagger
 * /api/question-sources/{id}:
 *   patch:
 *     summary: 更新题目来源文档的任意字段
 *     description: 更新指定ID文档的一个或多个字段
 *     tags: [QuestionSource]
 *     parameters:
 *       - in: path
 *         name: id
 *         schema:
 *           type: string
 *         required: true
 *         description: 题目来源文档ID
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             properties:
 *               sourceType:
 *                 type: string
 *               sourceContent:
 *                 type: string
 *     responses:
 *       200:
 *         description: 成功更新文档
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/QuestionSource'
 *       400:
 *         description: 无效更新操作
 *       404:
 *         description: 未找到指定文档
 */
exports.updateSourceById = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const updates = Object.keys(req.body);
  const allowedUpdates = ['sourceType', 'sourceContent'];
  
  // 验证更新字段
  const isValidOperation = updates.every(update => allowedUpdates.includes(update));
  if (!isValidOperation) {
    res.status(400);
    throw new Error('无效更新操作,请求体不正确');
  }

  // 验证请求体格式
  if (!req.body || typeof req.body !== 'object') {
    res.status(400);
    throw new Error('无效的请求体格式');
  }

  // 验证文档ID格式
  if (!mongoose.Types.ObjectId.isValid(id)) {
    res.status(400);
    throw new Error('无效的ID格式');
  }
  
  const source = await QuestionSource.findById(id);
  if (!source) {
    res.status(404);
    throw new Error('未找到指定文档');
  }
   /**
     *  ​**source[update] = req.body[update] 的含义**​
​     *  这行代码的意思是：
     ​*  ​**source[update]**​：访问 source 对象的属性，属性名是 update 的值（即当前遍历到的字段名，如 "sourceType" 或 "sourceContent"）。
     ​*  例如，如果 update = "sourceType"，那么 source[update] 就是 source.sourceType。
​​     *  **req.body[update]**​：从请求体（req.body）中获取对应字段的值。
​     *  例如，如果 update = "sourceType"，那么 req.body[update] 就是 req.body.sourceType（即客户端传入的 sourceType 值）。
​​     *  **=**​：将请求体中的值赋给 source 对象的对应属性。
     */

  // 应用更新
  updates.forEach(update => {
    source[update] = req.body[update];
  });
  
  await source.save();
  
  res.status(200).json({ 
    success: true,
    data: source
  });
});

/**
 * @swagger
 * /api/question-sources/cascader-options:
 *   get:
 *     summary: 获取级联选择器数据
 *     description: 返回嵌套的级联选择器数据结构
 *     tags: [QuestionSource]
 *     responses:
 *       200:
 *         description: 成功获取数据
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 data:
 *                   type: array
 *                   items:
 *                     type: object
 *                     properties:
 *                       value:
 *                         type: string
 *                         description: 选项值
 *                       label:
 *                         type: string
 *                         description: 选项显示文本
 *                       id:
 *                         type: string
 *                         description: 来源于数据库id
 *                       children:
 *                         type: array
 *                         items:
 *                           $ref: '#/components/schemas/CascaderOption'
 *               example:
 *                 success: true
 *                 data:
 *                   - value: "teacher"
 *                     label: "教师"
 *                     id: "6881f1865b55611d189502f2"
 *                     children:
 *                       - value: "primary"
 *                         label: "小学"
 *                         id: "6881f1725b55611d189502e5"
 *                         children: []
 */

/**
 * @description 获取级联选择器选项数据
 * 1. 从QuestionSource集合中获取所有唯一的sourceType并按创建时间排序
 * 2. 根据sourceType动态构建级联选择器所需的嵌套结构
 * 3. 每个层级的选项来自对应sourceType的sourceContent字段
 */
exports.getCascaderOptions = asyncHandler(async (req, res) => {
  // 1. 获取所有唯一的sourceType并按createdAt升序排序
  const sourceTypes = await QuestionSource.aggregate([
    { 
      $group: { 
        _id: "$sourceType", // 这个地方使用_id作为分组字段，这个_id并不是文档中的那个_id，只是重名而已
        // 把原来的文档中的_id也就给他替换成了sourceType的值了
        createdAt: { $first: "$createdAt" } 
      } 
    },
    { 
      $sort: { createdAt: 1 } 
    }
  ]);
  /**
   *  console.log(sourceTypes);
   * [
         { _id: 'a', createdAt: 2025-07-28T09:12:42.566Z },
         { _id: 'b', createdAt: 2025-07-28T09:12:56.743Z },
         { _id: 'c', createdAt: 2025-07-28T14:19:18.675Z }
     ]
   */
 

  // 2. 获取所有QuestionSource记录用于构建选项
  const sources = await QuestionSource.find();

  // 3. 按sourceType组织数据，构建{ sourceType: [options] }的映射
  const typeData = {};
  sourceTypes.forEach(type => {
    /**
     * console.log(type);
     * 打印结果：
     * { _id: 'a', createdAt: 2025-07-28T09:12:42.566Z }
     * { _id: 'b', createdAt: 2025-07-28T09:12:56.743Z }
     * 使用Map确保每个sourceContent只保留一个记录（取最早创建的记录）
     */
    const contentMap = new Map();
    sources
      .filter(s => s.sourceType === type._id) //这里的_id不是mongoose的_id，是上面分组的依据，是sourceType的_id
      .sort((a, b) => a.createdAt - b.createdAt) // 按创建时间排序
      .forEach(s => {
        if (!contentMap.has(s.sourceContent)) {
          contentMap.set(s.sourceContent, {
            content: s.sourceContent,
          //id2: s._id.toString(), // 转换为字符串格式 并赋值给id,效果和下面一样
            id:s.id
          });
        }
      });
    /**
     * console.log(contentMap);
      * 打印结果：
      Map(2) {
        'a.1' => {
            content: 'a.1',
            id: '68873f0ae724a0196ff85253',
            id2: '68873f0ae724a0196ff85253'
        },
       'a.2' => {
            content: 'a.2',
            id: '68873f10e724a0196ff85257',
            id2: '68873f10e724a0196ff85257'
        }
      }
      Map(2) {
        'b.1' => {
             content: 'b.1',
             id: '68873f18e724a0196ff8525c',
             id2: '68873f18e724a0196ff8525c'
         },
        'b.2' => {
             content: 'b.2',
             id: '688786d7697ffdbebfb14acd',
             id2: '688786d7697ffdbebfb14acd'
         }
      }
      Map(2) {
         'c.1' => {
             content: 'c.1',
             id: '688786e6697ffdbebfb14ad2',
             id2: '688786e6697ffdbebfb14ad2'
           },
          'c.2' => {
             content: 'c.2',
             id: '688786ec697ffdbebfb14ad6',
             id2: '688786ec697ffdbebfb14ad6'
            }
       }
    */
    //  console.log(Array.from(contentMap.values()));
      typeData[type._id] = Array.from(contentMap.values());
    //  console.log(type._id); a,b,c
    //console.log(typeData);
  });

  

  /**
   * @description 递归构建级联选择器数据结构
   * @param {number} currentIndex 当前处理的sourceType索引
   * @returns {Array} 当前层级的级联选项数组
   */
  const buildLevel = (currentIndex) => {
    // 终止条件：处理完所有sourceType
    if (currentIndex >= sourceTypes.length) return [];
    
    const currentType = sourceTypes[currentIndex]._id;
    return typeData[currentType].map(item => ({
      value: item.content,
      label: item.content,
      id: item.id, // 添加id字段（数据库中的id）
      children: buildLevel(currentIndex + 1)
    }));
  };

  // 4. 从第一个sourceType开始构建完整级联结构
  const cascaderData = buildLevel(0);
  
  res.status(200).json({ 
    success: true, 
    data: cascaderData 
  });
});

/**
 * @swagger
 * /api/question-sources/map-source:
 *   get:
 *     summary: 获取分类结构的题目来源数据
 *     description: 返回按分类组织的题目来源数据
 *     tags: [QuestionSource]
 *     responses:
 *       200:
 *         description: 成功获取分类结构数据
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 data:
 *                   type: object
 *                   properties:
 *                     categories:
 *                       type: array
 *                       items:
 *                         type: string
 *                       description: 分类名称列表
 *                     contentsMap:
 *                       type: object
 *                       additionalProperties:
 *                         type: array
 *                         items:
 *                           type: object
 *                           properties:
 *                             id:
 *                               type: string
 *                             title:
 *                               type: string
 *       500:
 *         description: 服务器错误
 */
exports.getMapSource = asyncHandler(async (req, res) => {
  // 获取所有题目来源记录
  const sources = await QuestionSource.find();
  
  // 提取唯一分类名称
  const categories = [...new Set(sources.map(item => item.sourceType))];
  
  // 构建分类内容映射
  const contentsMap = {};
  sources.forEach(source => {
    const type = source.sourceType;
    if (!contentsMap[type]) {
      contentsMap[type] = [];
    }
    contentsMap[type].push({
      id: source.id, 
      title: source.sourceContent
    });
  });
  
  res.status(200).json({
    success: true,
    data: {
      categories,
      contentsMap
    }
  });
});

/**
 * @swagger
 * /api/question-sources/source-types:
 *   get:
 *     summary: 获取所有的题目来源类型sorceType
 *     description: 获取所有不重复的题目来源类型列表
 *     tags: [QuestionSource]
 *     responses:
 *       200:
 *         description: 成功获取来源类型列表
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 data:
 *                   type: array
 *                   items:
 *                     type: string
 *       500:
 *         description: 服务器错误
 */
exports.getUniqueSourceTypes = asyncHandler(async (req, res) => {
  const questionSources = await QuestionSource.find().distinct('sourceType');
  res.status(200).json({ 
    success: true,
    data: questionSources
  });
});

/**
 * @swagger
 * /api/question-sources?oldSourceType=X:
 *   patch:
 *     summary: 批量重命名分类
 *     description: 将所有旧分类名的文档更新为新分类名
 *     tags: [QuestionSource]
 *     parameters:
 *       - in: query
 *         name: oldSourceType
 *         schema:
 *           type: string
 *         required: true
 *         description: 旧分类名
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             properties:
 *               newSourceType:
 *                 type: string
 *                 description: 新分类名
 *             required:
 *               - newSourceType
 *     responses:
 *       200:
 *         description: 成功更新文档
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 message:
 *                   type: string
 *       400:
 *         description: 缺少必要参数
 *       404:
 *         description: 未找到指定来源类型
 *       409:
 *         description: 新分类名已被使用
 *       500:
 *         description: 服务器错误
 */
exports.batchRenameSourceType = asyncHandler(async (req, res) => {
  const { oldSourceType } = req.query;
  const { newSourceType } = req.body;
  
  if (!oldSourceType || !newSourceType) {
    res.status(400);
    throw new Error('缺少必要参数');
  }
  
  const result = await QuestionSource.updateMany(
    { sourceType: oldSourceType },
    { $set: { sourceType: newSourceType } }
  );
  
  // 版本兼容逻辑
  const matched = result.matchedCount ?? result.n;
  const modified = result.modifiedCount ?? result.nModified;
  
  if (matched === 0) {
    res.status(404);
    throw new Error('未找到指定的题目来源类型');
  }
  
  if (modified === 0) {
    return res.status(200).json({ 
      success: true,
      message: '文档已是最新状态，无需更新'
    });
  }
  
  res.status(200).json({ 
    success: true,
    message: `${modified} 个文档已更新`
  });
});


/**
 * @swagger
 * /api/question-sources?sourceType=X:
 *   delete:
 *     summary: 批量删除整个分类
 *     description: 根据查询参数sourceType删除所有匹配的文档
 *     tags: [QuestionSource]
 *     parameters:
 *       - in: query
 *         name: sourceType
 *         schema:
 *           type: string
 *         required: true
 *         description: 要删除的分类名称
 *     responses:
 *       200:
 *         description: 成功删除文档
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 message:
 *                   type: string
 *       400:
 *         description: 缺少必要参数
 *       404:
 *         description: 未找到指定分类
 *       409:
 *         description: 分类正在使用中，无法删除
 *       500:
 *         description: 服务器错误
 */
exports.batchDeleteSourceType = asyncHandler(async (req, res) => {
  const { sourceType } = req.query;
  
  if (!sourceType) {
    res.status(400);
    throw new Error('缺少 sourceType 查询参数');
  }
  
  const result = await QuestionSource.deleteMany({ sourceType });
  
  // 处理无匹配文档
  if (result.deletedCount === 0) {
    res.status(404);
    throw new Error('未找到指定的题目来源类型');
  }
  
  res.status(200).json({ 
    success: true,
    message: `${result.deletedCount} 个文档已删除`
  });
});


/**
 * @swagger
 * /api/question-sources/{sourceType}/source-contents:
 *   get:
 *     summary: 获取来源类型的内容列表
 *     description: 获取指定来源类型的所有内容选项
 *     tags: [QuestionSource]
 *     parameters:
 *       - in: path
 *         name: sourceType
 *         schema:
 *           type: string
 *         required: true
 *         description: 要查询的来源类型
 *     responses:
 *       200:
 *         description: 成功获取来源选项
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 data:
 *                   type: object
 *                   properties:
 *                     sourceType:
 *                       type: string
 *                     sourceContents:
 *                       type: array
 *                       items:
 *                         type: object
 *                         properties:
 *                           id:
 *                             type: string
 *                           content:
 *                             type: string
 *       400:
 *         description: 缺少sourceType查询参数
 *       404:
 *         description: 未找到指定来源类型
 *       500:
 *         description: 服务器错误
 */
exports.getSourceContents = asyncHandler(async (req, res) => {
  const { sourceType } = req.params;
  
  if (!sourceType) {
    res.status(400);
    throw new Error('缺少sourceType路径参数');
  }
  
  const sources = await QuestionSource.find({ sourceType }).lean();
  
  if (!sources || sources.length === 0) {
    res.status(404);
    throw new Error('未找到指定的题目来源类型');
  }

  // 构建返回数据结构
  const data = {
    sourceType,
    sourceContents: sources.map(item => ({ id: item.id, content: item.sourceContent }))
  };

  res.status(200).json({
    success: true,
    data
  });
});

/**
 * @swagger
 * /api/question-sources/{id}:
 *   delete:
 *     summary: 删除单个题目来源文档
 *     description: 根据ID删除特定题目来源文档
 *     tags: [QuestionSource]
 *     parameters:
 *       - in: path
 *         name: id
 *         schema:
 *           type: string
 *         required: true
 *         description: 题目来源文档ID
 *     responses:
 *       200:
 *         description: 成功删除文档
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 message:
 *                   type: string
 *       404:
 *         description: 未找到指定文档
 *       400:
 *         description: ID格式不正确
 */
exports.deleteSourceById = asyncHandler(async (req, res) => {
  const { id } = req.params;
  
  // 验证文档ID格式
  if (!mongoose.Types.ObjectId.isValid(id)) {
    res.status(400);
    throw new Error('无效的ID格式');
  }
  
  // 使用ID查找并删除
  const questionSource = await QuestionSource.findByIdAndDelete(id);
  
  if (!questionSource) {
    res.status(404);
    throw new Error('未找到指定的题目来源类型');
  }
  
  res.status(200).json({ 
    success: true,
    message: '文档已删除'
  });
});